package com.muqiuhan.osmanthus.models

import com.muqiuhan.osmanthus.utils.ContextUtils
import org.springframework.beans.factory.NoSuchBeanDefinitionException
import java.lang.reflect.*
import scala.util.{Failure, Try, Success}

/** Task execution method, used to serialize and save in the database. */
case class Invocation(
    targetClass: Class[AnyRef],
    methodName: String,
    parameterTypes: Class[AnyRef],
    args: AnyRef*
) extends Serializable:

  private implicit class ClassMethod(target: Class[?] | Any):
    inline def method: Method =
      target.getClass.getMethod(methodName, parameterTypes)
  end ClassMethod

  private implicit class InvokeMethod(method: Method):
    inline def invoke: AnyRef =
      method.invoke(targetClass.getDeclaredConstructor().newInstance())
  end InvokeMethod

  def invoke: AnyRef =
    Try[AnyRef](ContextUtils.getBeanByClass(targetClass)) match
      case Failure(e: NoSuchBeanDefinitionException) => Class.forName(targetClass.getName).method.invoke
      case Success(target: Option[?]) =>
        target match
          case Some(target) => target.method.invoke
          case None         => throw RuntimeException(s"Cannot getBeanByClass: $targetClass")
      case scala.util.Failure(e)      => throw e
      case scala.util.Success(target) => throw RuntimeException(s"Unable to handle this target of $targetClass")
    end match
  end invoke

end Invocation
